#include "StdAfx.h"
#include "DOMNode.h"



char* DOMNode::Block_Tags[]={"ADDRESS",    /* ADDRESS - Address  */                                                                                                    
                             "BLOCKQUOTE", /* BLOCKQUOTE - Block quotation  */                                                                                         
							 "CENTER",     /* CENTER - Centered block  */                                                                                              
							 "DIR",        /* DIR - Directory list  */                                                                                                 
							 "DIV",        /* DIV - Generic block-level container  */                                                                                  
							 "DL",         /* DL - Definition list  */                                                                                                 
							 "FIELDSET",   /* FIELDSET - Form control group  */                                                                                        
							 "FORM",       /* FORM - Interactive form  */                                                                                              
							 "H1",         /* H1 - Level-one heading  */                                                                                               
							 "H2",         /* H2 - Level-two heading  */                                                                                               
							 "H3",         /* H3 - Level-three heading  */                                                                                             
							 "H4",         /* H4 - Level-four heading  */                                                                                              
							 "H5",         /* H5 - Level-five heading  */                                                                                              
							 "H6",         /* H6 - Level-six heading  */                                                                                               
							 "HR",         /* HR - Horizontal rule  */                                                                                                 
							 "ISINDEX",    /* ISINDEX - Input prompt  */                                                                                               
							 "MENU",       /* MENU - Menu list  */                                                                                                     
							 "NOFRAMES",   /* NOFRAMES - Frames alternate content  */                                                                                  
							 "NOSCRIPT",   /* NOSCRIPT - Alternate script content  */                                                                                  
							 "OL",         /* OL - Ordered list  */                                                                                                    
							 "P",          /* P - Paragraph  */                                                                                                        
							 "PRE",        /* PRE - Preformatted text  */                                                                                              
							 "SPAN",       /* SPAN - generic inline container.*/
							 "TABLE",      /* TABLE - Table  */                                                                                                        
							 "UL",         /* UL - Unordered list  */                                                                                                  
/* The following elements may also be considered block-level elements since they may contain block-level elements:  */      
							 "DD",         /* DD - Definition description  */                                                                                          
							 "DT",         /* DT - Definition term  */                                                                                                 
							 "FRAMESET",   /* FRAMESET - Frameset  */                                                                                                  
							 "LI",         /* LI - List item  */                                                                                                       
							 "TBODY",      /* TBODY - Table body  */                                                                                                   
							 "TD",         /* TD - Table data cell  */                                                                                                 
                             "TFOOT",      /* TFOOT - Table foot  */                                                                                                   
                             "TH",         /* TH - Table header cell  */                                                                                               
                             "THEAD",      /* THEAD - Table head  */                                                                                                   
                             "TR"          /* TR - Table row  */                                                                                                       
};

char* DOMNode::inline_tags[]={"TT",          /* TT: Renders as teletype or monospaced text.  */                                 
							  "I",           /* I: Renders as italic text style.  */                                            
							  "B",           /* B: Renders as bold text style.  */                                              
							  "BIG",         /* BIG: Renders text in a "large" font.  */                                        
							  "SMALL",       /* SMALL: Renders text in a "small" font.  */                                      
							  "STRIKE",      /* STRIKE: Render strike-through style text.  */   
							  "S",           /* S: Render strike-through style text.  */                                                             
							  "U",           /* U: Renders underlined text.  */                                                 
							  "EM",          /* EM: Indicates emphasis.  */                                                     
							  "STRONG",      /* STRONG: Indicates stronger emphasis.  */                                        
							  "CITE",        /* CITE: Contains a citation or a reference to other sources.  */                  
							  "DFN",         /* DFN: Indicates that this is the defining instance of the enclosed term.  */     
							  "CODE",        /* CODE: Designates a fragment of computer code.  */                               
							  "SAMP",        /* SAMP: Designates sample output from programs, scripts, etc.  */                 
							  "KBD",         /* KBD: Indicates text to be entered by the user.  */                              
							  "VAR",         /* VAR: Indicates an instance of a variable or program argument.  */               
							  "ABBR",        /* ABBR: Indicates an abbreviated form (e.g., WWW, HTTP, URI, Mass., etc.).  */    
							  "ACRONYM"      /* ACRONYM: Indicates an acronym (e.g., WAC, radar, etc.).  */                     
							};



bool DOMNode::Dividable(){

	//rule1. divide root and body node
	if( m_TagName.CompareNoCase("root") ==0 ||
		m_TagName.CompareNoCase("body") ==0 ){
			return true;
		}

	for(int i=0;i<sizeof(Block_Tags)/sizeof(char*);i++){
		if(m_TagName.CompareNoCase(Block_Tags[i])==0)
			return false;
	}
	//rule2 if no link in the sub tree, dont divide
	if(m_nLinkNum==0)
		return false;
	//rule3 only has one child and the child is not a text node, divide it
	if(m_Children.size()== 1 && (m_Children[0]->m_nType==ELEMENT_TYPE) )
		return true;
	//rule4 if one of the child nodes is line-break node, divide it
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		if((*i)->m_nLineType == LINE_BREAK_NODE)
			return true;
	}
	//rule5 if contains HR tag, divide it
	if(Contains("HR"))
		return true;
	//rule6 if background of one of the children is different from the node, divide it
	if( !DiffBkChild())
		return true;

	return false;
}
//recursively add the children for current node
void DOMNode::AddChildren(){
    CComPtr<IDispatch> spCollectionDispatch;
	if ( SUCCEEDED( m_pDOMNode->get_childNodes( &spCollectionDispatch)))
	{
		long numChildren = 0;
		CComQIPtr<IHTMLDOMChildrenCollection> spCollection = spCollectionDispatch;
		if (!! spCollection)
		{
			spCollection->get_length( &numChildren);
			for ( long i = 0; i < numChildren; i++)
			{
				CComPtr<IDispatch> spItemDispatch;
				spCollection->item( i, &spItemDispatch);
				if ( !!spItemDispatch)
				{
					CComQIPtr<IHTMLDOMNode> spItemNode = spItemDispatch;
					if ( !!spItemNode)
					{
						m_Children.push_back(new DOMNode(spItemNode));
					}							
				}
			}
		}
	}
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		(*i)->AddChildren();
	}
}

void DOMNode::RootFirstVisit(){
//	AfxMessageBox(m_TagName);
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		(*i)->RootFirstVisit();
	}
}


bool DOMNode::Contains(const CString& tagName){
	bool bRet=false;
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		bRet |= (*i)->TreeContains(tagName);
	}
	return bRet;
}


bool DOMNode::TreeContains(const CString& tagName){
	if(m_TagName.CompareNoCase(tagName) == 0)
		return true;
	bool bRet=false;
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		bRet |= (*i)->TreeContains(tagName);
	}
	return bRet;
}

void DOMNode::CalcTreeInfo(){
	if(m_Children.size() == 0){
		m_nTextLength=StrLength(m_Value);
		return;
	}else if(m_TagName.CompareNoCase("a")==0){ // a link
		m_nLinkNum=1;
		m_nTextLength=0;
		return;
	}	
	for(std::vector<DOMNode*>::iterator i=m_Children.begin();i!=m_Children.end();i++){
		(*i)->CalcTreeInfo();
		m_nLinkNum+=(*i)->m_nLinkNum;
		m_nTextLength+=(*i)->m_nTextLength;		
	}
}

CString DOMNode::Variant2Str(const CComVariant& var){
	USES_CONVERSION;
	CString strRet;

	if ( var.vt != VT_EMPTY && var.vt != VT_NULL)
	{
		if ( var.vt == VT_BSTR)
		{
			if ( var.bstrVal != NULL)
				strRet = W2T( var.bstrVal);
			else
				strRet = "";
		}
		else if ( var.vt == VT_I4)
		{
			CString number;
			number.Format(_T("%d"), var.intVal);
			strRet=number;
		}
	}
	else
		strRet="";

	return strRet;
}

void DOMNode::InsertAttr(const CComBSTR& name, const CComVariant& value){	
	USES_CONVERSION;   //to use string conversion in ATL
	static CString strvalnull(_T("null"));

	CString strName(W2T(name));

	if ( value.vt != VT_EMPTY && value.vt != VT_NULL)
	{
		if ( value.vt == VT_BSTR)
		{
			if ( value.bstrVal != NULL)
				m_attrs[strName]=CString(W2T( value.bstrVal));
			else
				m_attrs[strName]=strvalnull;
		}
		else if ( value.vt == VT_I4)
		{
			CString number;
			number.Format(_T("%d"), value.intVal);
			m_attrs[strName]=number;
		}
	}
	else
		m_attrs[strName]=strvalnull;		
}


void DOMNode::GetCurrentStyleText(){
	CComQIPtr<IHTMLElement2> pElem2=m_pDOMNode;
	if(!!pElem2){
		CComPtr<IHTMLCurrentStyle> spCurrentStyle;
		pElem2->get_currentStyle(&spCurrentStyle);
		CComBSTR strValue;
		CComVariant varValue;
		if(!!spCurrentStyle){		
			if(SUCCEEDED(spCurrentStyle->get_backgroundAttachment(&strValue))){
				m_currentStyleText += "backgroundAttachment:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_backgroundColor(&varValue))){
				m_currentStyleText += "backgroundColor:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
				m_strBkColor=Variant2Str(varValue);
			}
			if(SUCCEEDED(spCurrentStyle->get_backgroundImage(&strValue))){
				m_currentStyleText += "backgroundImage:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_backgroundPositionX(&varValue))){
				m_currentStyleText += "backgroundPositionX:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_backgroundPositionY(&varValue))){
				m_currentStyleText += "backgroundPositionY:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_backgroundRepeat(&strValue))){
				m_currentStyleText += "backgroundRepeat:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_behavior(&strValue))){
				m_currentStyleText += "behavior:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_blockDirection(&strValue))){
				m_currentStyleText += "blockDirection:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderBottomColor(&varValue))){
				m_currentStyleText += "borderBottomColor:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderBottomStyle(&strValue))){
				m_currentStyleText += "borrderBottomStyle:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderBottomWidth(&varValue))){
				m_currentStyleText += "borderBottomWidth:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderCollapse(&strValue))){
				m_currentStyleText += "borderCollapse:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderColor(&strValue))){
				m_currentStyleText += "borderColor:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderLeftColor(&varValue))){
				m_currentStyleText += "borderLeftColor:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderLeftStyle(&strValue))){
				m_currentStyleText += "borderLeftStyle:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderLeftWidth(&varValue))){
				m_currentStyleText += "borderLeftWidth:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderRightColor(&varValue))){
				m_currentStyleText += "borderRightColor:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderRightStyle(&strValue))){
				m_currentStyleText += "borderRightStyle:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderRightWidth(&varValue))){
				m_currentStyleText += "borderRightWidth:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderTopColor(&varValue))){
				m_currentStyleText += "borderTopColor:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderTopStyle(&strValue))){
				m_currentStyleText += "borderTopStyle:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_borderTopWidth(&varValue))){
				m_currentStyleText += "borderTopWidth:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}			
			if(SUCCEEDED(spCurrentStyle->get_borderWidth(&strValue))){
				m_currentStyleText += "borderWidth:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_bottom(&varValue))){
				m_currentStyleText += "bottom:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_clear(&strValue))){
				m_currentStyleText += "clear:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_clipBottom(&varValue))){
				m_currentStyleText += "clipBottom:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_clipLeft(&varValue))){
				m_currentStyleText += "clipLeft:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_clipRight(&varValue))){
				m_currentStyleText += "clipRight:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_clipTop(&varValue))){
				m_currentStyleText += "clipTop:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_color(&varValue))){
				m_currentStyleText += "color:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
				m_strForeColor=Variant2Str(varValue);
			}
			if(SUCCEEDED(spCurrentStyle->get_cursor(&strValue))){
				m_currentStyleText += "cursor:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_direction(&strValue))){
				m_currentStyleText += "direction:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_display(&strValue))){
				m_currentStyleText += "display:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_fontFamily(&strValue))){
				m_currentStyleText += "fontFamily:";
				m_currentStyleText+=strValue;
				m_strFontFamily=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_fontSize(&varValue))){
				m_currentStyleText += "fontSize:";
				m_currentStyleText+=Variant2Str(varValue);
				m_strFontSize=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_fontStyle(&strValue))){
				m_currentStyleText += "fontStyle:";
				m_currentStyleText+=strValue;
				m_strFontStyle=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_fontVariant(&strValue))){
				m_currentStyleText += "fontVariant:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_fontWeight(&varValue))){//different from document
				m_currentStyleText += "fontWeight:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_height(&varValue))){
				m_currentStyleText += "height:";
				m_currentStyleText+=Variant2Str(varValue);
				m_strFontWeight=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_imeMode(&strValue))){
				m_currentStyleText += "imeMode:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_layoutGridChar(&varValue))){
				m_currentStyleText += "layoutGridChar:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_layoutGridLine(&varValue))){
				m_currentStyleText += "layoutGridLine:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_layoutGridMode(&strValue))){
				m_currentStyleText += "layoutGridMode:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_layoutGridType(&strValue))){
				m_currentStyleText += "layoutGridType:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_left(&varValue))){
				m_currentStyleText += "left:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_letterSpacing(&varValue))){
				m_currentStyleText += "letterSpacing:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_lineBreak(&strValue))){
				m_currentStyleText += "lineBreak:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_lineHeight(&varValue))){
				m_currentStyleText += "lineHeight:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_listStyleImage(&strValue))){
				m_currentStyleText += "listStyleImage:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_listStylePosition(&strValue))){
				m_currentStyleText += "listStylePosition:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_listStyleType(&strValue))){
				m_currentStyleText += "listStyleType:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_margin(&strValue))){
				m_currentStyleText += "margin:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_marginBottom(&varValue))){
				m_currentStyleText += "marginBottom:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_marginLeft(&varValue))){
				m_currentStyleText += "marginLeft:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_marginRight(&varValue))){
				m_currentStyleText += "marginRight:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_marginTop(&varValue))){
				m_currentStyleText += "marginTop:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_overflow (&strValue))){
				m_currentStyleText += "overflow:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_overflowX(&strValue))){
				m_currentStyleText += "overflowX:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_overflowY(&strValue))){
				m_currentStyleText += "overflowY:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_padding(&strValue))){
				m_currentStyleText += "padding:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_paddingBottom(&varValue))){
				m_currentStyleText += "paddingBottom:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_paddingLeft(&varValue))){
				m_currentStyleText += "paddingLeft:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_paddingRight(&varValue))){
				m_currentStyleText += "paddingRight:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_paddingTop(&varValue))){
				m_currentStyleText += "paddingTop:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_pageBreakAfter(&strValue))){
				m_currentStyleText += "pageBreakAfter:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_pageBreakBefore(&strValue))){
				m_currentStyleText += "pageBreakBefore:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";

			}
			if(SUCCEEDED(spCurrentStyle->get_position(&strValue))){
				m_currentStyleText += "position:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_right(&varValue))){
				m_currentStyleText += "right:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_rubyAlign(&strValue))){
				m_currentStyleText += "rubyAlign:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_rubyOverhang(&strValue))){
				m_currentStyleText += "rubyOverhang:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_rubyPosition(&strValue))){
				m_currentStyleText += "rubyPosition:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_styleFloat(&strValue))){
				m_currentStyleText += "styleFloat:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_tableLayout(&strValue))){
				m_currentStyleText += "tableLayout:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textAlign(&strValue))){
				m_currentStyleText += "textAlign:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textAutospace(&strValue))){
				m_currentStyleText += "textAutospace:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textDecoration(&strValue))){
				m_currentStyleText += "textDecoration:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textIndent(&varValue))){
				m_currentStyleText += "textIndent:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textJustify(&strValue))){
				m_currentStyleText += "textJustify:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_textTransform(&strValue))){
				m_currentStyleText += "textTransform:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_top(&varValue))){
				m_currentStyleText += "top:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_unicodeBidi(&strValue))){
				m_currentStyleText += "unicodeBidi:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_verticalAlign(&varValue))){
				m_currentStyleText += "verticalAlign:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_visibility(&strValue))){
				m_currentStyleText += "visibility:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_width(&varValue))){
				m_currentStyleText += "width:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_wordBreak(&strValue))){
				m_currentStyleText += "wordBreak:";
				m_currentStyleText+=strValue;
				m_currentStyleText+="\r\n";
			}
			if(SUCCEEDED(spCurrentStyle->get_zIndex(&varValue))){
				m_currentStyleText += "zIndex:";
				m_currentStyleText+=Variant2Str(varValue);
				m_currentStyleText+="\r\n";
			}
		}
	}
}
void DOMNode::GetVisualInfo(){
	m_lTop=0;
	m_lLeft=0;
	m_lWidth=0;
	m_lHeight=0;		
	long lValue=0;
	CComQIPtr<IHTMLElement> pElem=m_pDOMNode;
	if(!!pElem){

		pElem->get_offsetLeft(&lValue);m_lLeft=lValue;
		pElem->get_offsetTop(&lValue);m_lTop=lValue;
		pElem->get_offsetWidth(&lValue);m_lWidth=lValue;
		pElem->get_offsetHeight(&lValue);m_lHeight=lValue;

		IHTMLElement* pContainerElem=NULL;  //an assert occured when using the smart pointer
		pElem->get_offsetParent(&pContainerElem);
		while (!! pContainerElem) {
			pContainerElem->get_offsetLeft(&lValue); m_lLeft += lValue;
			pContainerElem->get_offsetTop(&lValue);  m_lTop += lValue;
			pContainerElem->get_offsetParent(&pContainerElem);
		}

		CComBSTR cssText;
		CComPtr<IHTMLStyle> pStyle;
		pElem->get_style(&pStyle);
		pStyle->get_cssText(&cssText);
		m_cssText=cssText;
	}
	m_nAppearType=NON_VALID_NODE;
	if(m_lWidth && m_lHeight){ 
		m_nAppearType=VALID_NODE;
	}
	return;
}

void DOMNode::GetAttrInfo()
{
	CComQIPtr<IHTMLAttributeCollection> spAttrColl;
	CComPtr<IDispatch> disp;
	m_pDOMNode->get_attributes(&disp);
	spAttrColl=disp;

	if (!! spAttrColl) {
		long numChildren = 0;
		spAttrColl->get_length( &numChildren);
		for ( long i = 0; i < numChildren; i++)
		{
			CComVariant index( i);
			CComPtr<IDispatch> spItemDispatch;
			spAttrColl->item( &index, &spItemDispatch);
			if ( spItemDispatch != NULL)
			{
				CComQIPtr<IHTMLDOMAttribute> spAttribute = spItemDispatch;
				if ( spAttribute != NULL)
				{
					VARIANT_BOOL bspecified = VARIANT_FALSE;
					spAttribute->get_specified( &bspecified);
					if(bspecified == VARIANT_TRUE){
						CComBSTR name;
						CComVariant value;							
						spAttribute->get_nodeName( &name);
						spAttribute->get_nodeValue( &value); 
						InsertAttr( name, value);
					}									
				}
			}
		}
	}
}


// get the information for an element which neednt look the children of the node
void DOMNode::GetElementInfo()
{
	CComBSTR tagName;
	CComVariant Value;
	long lType;

	m_pDOMNode->get_nodeName(&tagName);
	m_TagName=tagName;

	m_pDOMNode->get_nodeType(&lType);
	m_nType = lType==1? ELEMENT_TYPE : TEXT_TYPE;
	if(m_nType != ELEMENT_TYPE){//element type never has value
		m_pDOMNode->get_nodeValue(&Value);		
		if(Value.vt == VT_BSTR)	{
			m_Value=Value.bstrVal;				
		}			
	}
	
	m_nLineType=LINE_BREAK_NODE;
	for(int i=0;i<sizeof(inline_tags)/sizeof(char*);i++){
		if(m_TagName.CompareNoCase(inline_tags[i])==0)
			m_nLineType=INLINE_NODE;
	}	
}
CString DOMNode::toString()
{
	CString strInfo;
	strInfo.Format("Tag:%s\r\nType:%s\r\nValue:%s\r\n",m_TagName,m_nType==ELEMENT_TYPE?"element":"text",m_Value);
	for(std::map<CString,CString>::iterator i=m_attrs.begin();i!=m_attrs.end();i++){
		strInfo+=i->first;
		strInfo+=":";
		strInfo+=i->second;
		strInfo+="\r\n";
	}
	CString strVisualInfo;
	strVisualInfo.Format("left:%d\r\ntop:%d\r\nwidth:%d\r\nheight:%d\r\n",
		m_lLeft,m_lTop,m_lWidth,m_lHeight);
	strInfo+=strVisualInfo;
	strInfo+=m_currentStyleText;
	return strInfo;
}

int DOMNode::StrLength(const CString &strText)
{
	CString strValue(strText);
	strValue.Replace(" ","");
	return strValue.GetLength();
}


DOMNode* DOMNode::DiffBkChild() // only look down one level
{
	std::vector<DOMNode*>::iterator i;
	for(i=m_Children.begin();i!=m_Children.end();i++){
		if((*i)->m_strBkColor.CompareNoCase("transparent")==0)
			continue;
		if(m_strBkColor.CompareNoCase( (*i)->m_strBkColor ) !=0 ){
			return *i;
		}
	}
	return *i;
}


void DOMNode::ShowRect()
{
	if(m_bShowed)
		return;
	CComQIPtr<IHTMLElement> pElem = m_pDOMNode;
	if(!pElem)
		return;
	CComPtr<IHTMLStyle> pStyle;
	pElem->get_style(&pStyle);
	pStyle->get_border(&m_strOldBorder);
	
	static CComBSTR strBox("2px red solid");	
	pStyle->put_border(strBox);
	//pStyle->put_borderBottom(strBox);
	m_bShowed=true;
}


void DOMNode::RestoreRect()
{
	if(!m_bShowed)
		return;
	m_bShowed=false;
	CComQIPtr<IHTMLElement> pElem = m_pDOMNode;
	if(!pElem)
		return;
	CComPtr<IHTMLStyle> pStyle;
	pElem->get_style(&pStyle);
	pStyle->put_border(m_strOldBorder);
}